home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xroach-v12 / xroach.c < prev    next >
C/C++ Source or Header  |  1995-06-20  |  16KB  |  784 lines

  1. /*
  2.     Xroach - A game of skill.  Try to find the roaches under your windows.
  3.     
  4.     Copyright 1991 by J.T. Anderson
  5.  
  6.     jta@locus.com
  7.     
  8.     This program may be freely distributed provided that all
  9.     copyright notices are retained.
  10.  
  11.     To build:
  12.       cc -o xroach roach.c -lX11 [-lsocketorwhatever] [-lm] [-l...]
  13.  
  14.     Dedicated to Greg McFarlane.   (gregm@otc.otca.oz.au)
  15.     
  16.     Squish option contributed by Rick Petkiewizc (rick@locus.com)
  17.     
  18.     Virtual root code adapted from patch sent by Colin Rafferty who
  19.     borrowed it from Tom LaStrange.  Several other folks sent similar
  20.     fixes.
  21. */
  22.  
  23. /* @(#)xroach.c    1.5 4/2/91 11:53:31 */
  24.  
  25. #include <X11/Xlib.h>
  26. #include <X11/Xutil.h>
  27. #include <X11/Xos.h>
  28. #include <X11/Xatom.h>
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include <malloc.h>
  33. #include <signal.h>
  34.  
  35. #if __STDC__
  36. #include <stdlib.h>
  37. #else
  38. long strtol();
  39. double strtod();
  40. char *getenv();
  41. #endif
  42.  
  43. char Copyright[] = "Xroach\nCopyright 1991 J.T. Anderson";
  44.  
  45. #include "roachmap.h"
  46.  
  47. typedef unsigned long Pixel;
  48. typedef int ErrorHandler();
  49.  
  50. #define SCAMPER_EVENT    (LASTEvent + 1)
  51.  
  52. #if !defined(GRAB_SERVER)
  53. #define GRAB_SERVER    0
  54. #endif
  55.  
  56. Display *display;
  57. int screen;
  58. Window rootWin;
  59. unsigned int display_width, display_height;
  60. int center_x, center_y;
  61. GC gc;
  62. GC gutsGC;
  63. char *display_name = NULL;
  64. Pixel black, white;
  65.  
  66. int done = 0;
  67. int eventBlock = 0;
  68. int errorVal = 0;
  69. Bool squishRoach = False;
  70. Pixmap squishMap;
  71. Bool squishWinUp = False;
  72.  
  73. typedef struct Roach {
  74.     RoachMap *rp;
  75.     int index;
  76.     float x;
  77.     float y;
  78.     int intX;
  79.     int intY;
  80.     int hidden;
  81.     int turnLeft;
  82.     int steps;
  83. } Roach;
  84.  
  85. Roach *roaches;
  86. int maxRoaches = 10;
  87. int curRoaches = 0;
  88. float roachSpeed = 20.0;
  89.  
  90. Region rootVisible = NULL;
  91.  
  92. void Usage();
  93. void SigHandler();
  94. void AddRoach();
  95. void MoveRoach();
  96. void DrawRoaches();
  97. void CoverRoot();
  98. int CalcRootVisible();
  99. int MarkHiddenRoaches();
  100. Pixel AllocNamedColor();
  101. Window FindRootWindow();
  102.  
  103. void
  104. main(ac, av)
  105. int ac;
  106. char *av[];
  107. {
  108.     XGCValues xgcv;
  109.     int ax;
  110.     char *arg;
  111.     RoachMap *rp;
  112.     int rx;
  113.     float angle;
  114.     XEvent ev;
  115.     char *roachColor = "black";
  116.     char *gutsColor = NULL;
  117.     int nVis;
  118.     int needCalc;
  119.     Window squishWin;
  120.     XSetWindowAttributes xswa;
  121.     
  122.     /*
  123.        Process command line options.
  124.     */
  125.     for (ax=1; ax<ac; ax++) {
  126.     arg = av[ax];
  127.     if (strcmp(arg, "-display") == 0) {
  128.         display_name = av[++ax];
  129.     }
  130.     else if (strcmp(arg, "-rc") == 0) {
  131.         roachColor = av[++ax];
  132.     }
  133.     else if (strcmp(arg, "-speed") == 0) {
  134.         roachSpeed = strtod(av[++ax], (char **)NULL);
  135.     }
  136.     else if (strcmp(arg, "-roaches") == 0) {
  137.         maxRoaches = strtol(av[++ax], (char **)NULL, 0);
  138.     }
  139.     else if (strcmp(arg, "-squish") == 0) {
  140.         squishRoach = True;
  141.     }
  142.     else if (strcmp(arg, "-rgc") == 0) {
  143.         gutsColor = av[++ax];
  144.     }
  145.     else {
  146.         Usage();
  147.     }
  148.     }
  149.  
  150.     srand((int)time((long *)NULL));
  151.     
  152.     /*
  153.        Catch some signals so we can erase any visible roaches.
  154.     */
  155.     signal(SIGKILL, SigHandler);
  156.     signal(SIGINT, SigHandler);
  157.     signal(SIGTERM, SigHandler);
  158.     signal(SIGHUP, SigHandler);
  159.  
  160.     display = XOpenDisplay(display_name);
  161.     if (display == NULL) {
  162.     if (display_name == NULL) display_name = getenv("DISPLAY");
  163.     (void) fprintf(stderr, "%s: cannot connect to X server %s\n", av[0],
  164.         display_name ? display_name : "(default)");
  165.     exit(1);
  166.     }
  167.  
  168.     screen = DefaultScreen(display);
  169.     rootWin = FindRootWindow();
  170.     black = BlackPixel(display, screen);
  171.     white = WhitePixel(display, screen);
  172.  
  173.     display_width = DisplayWidth(display, screen);
  174.     display_height = DisplayHeight(display, screen);
  175.     center_x = display_width / 2;
  176.     center_y = display_height / 2;
  177.     
  178.     /*
  179.        Create roach pixmaps at several orientations.
  180.     */
  181.     for (ax=0; ax<360; ax+=ROACH_ANGLE) {
  182.     rx = ax / ROACH_ANGLE;
  183.     angle = rx * 0.261799387799;
  184.     rp = &roachPix[rx];
  185.     rp->pixmap = XCreateBitmapFromData(display, rootWin,
  186.         rp->roachBits, rp->width, rp->height);
  187.     rp->sine = sin(angle);
  188.     rp->cosine = cos(angle);
  189.     }
  190.  
  191.     /*
  192.       Create the squished pixmap
  193.     */
  194.     if (squishRoach) {
  195.         squishMap = XCreateBitmapFromData(display, rootWin,
  196.         squish_bits, squish_width, squish_height);
  197.     }
  198.  
  199.     roaches = (Roach *)malloc(sizeof(Roach) * maxRoaches);
  200.  
  201.     gc = XCreateGC(display, rootWin, 0L, &xgcv);
  202.     XSetForeground(display, gc, AllocNamedColor(roachColor, black));
  203.     XSetFillStyle(display, gc, FillStippled);
  204.  
  205.     if (squishRoach && gutsColor != NULL) {
  206.         gutsGC = XCreateGC(display, rootWin, 0L, &xgcv);
  207.         XSetForeground(display, gutsGC, AllocNamedColor(gutsColor, black));
  208.         XSetFillStyle(display, gutsGC, FillStippled);
  209.     }
  210.     else
  211.     gutsGC = gc;
  212.     
  213.     while (curRoaches < maxRoaches)
  214.     AddRoach();
  215.     
  216.     XSelectInput(display, rootWin, ExposureMask | SubstructureNotifyMask);
  217.  
  218.     if (squishRoach) {
  219.     xswa.event_mask = ButtonPressMask;
  220.     xswa.override_redirect = True;
  221.     squishWin = XCreateWindow(display, rootWin, 0, 0,
  222.             display_width, display_height, 0,
  223.             CopyFromParent, InputOnly, CopyFromParent,
  224.             CWOverrideRedirect | CWEventMask, &xswa);
  225.     XLowerWindow(display, squishWin);
  226.     }
  227.     
  228.     needCalc = 1;
  229.     while (!done) {
  230.     if (XPending(display)) {
  231.         XNextEvent(display, &ev);
  232.     }
  233.     else {
  234.         if (needCalc) {
  235.         needCalc = CalcRootVisible();
  236.         }
  237.         if (needCalc)
  238.         nVis = 0;
  239.         else
  240.             nVis = MarkHiddenRoaches();
  241.         if (nVis) {
  242.         ev.type = SCAMPER_EVENT;
  243.         if (!squishWinUp && squishRoach) {
  244.             XMapWindow(display, squishWin);
  245.             squishWinUp = True;
  246.         }
  247.         }
  248.         else {
  249.         if (squishWinUp && squishRoach) {
  250.             XUnmapWindow(display, squishWin);
  251.             squishWinUp = False;
  252.         }
  253.         if (needCalc == 0)
  254.             DrawRoaches();
  255.         eventBlock = 1;
  256.         XNextEvent(display, &ev);
  257.         eventBlock = 0;
  258.         }
  259.     }
  260.     
  261.     switch (ev.type) {
  262.         
  263.         case SCAMPER_EVENT:
  264.         for (rx=0; rx<curRoaches; rx++) {
  265.             if (!roaches[rx].hidden)
  266.             MoveRoach(rx);
  267.         }
  268.         DrawRoaches();
  269.         XSync(display, False);
  270.         break;
  271.         
  272.         case UnmapNotify:
  273.         if (ev.xunmap.window != squishWin)
  274.             needCalc = 1;
  275.         break;
  276.  
  277.         case MapNotify:
  278.         case Expose:
  279.         case ConfigureNotify:
  280.         needCalc = 1;
  281.         break;
  282.     
  283.         case ButtonPress:
  284.         checkSquish(&ev);
  285.         break;
  286.         
  287.     }
  288.     }
  289.     
  290.     CoverRoot();
  291.     
  292.     XCloseDisplay(display);
  293. }
  294.  
  295. #define USEPRT(msg) fprintf(stderr, msg)
  296.  
  297. void
  298. Usage()
  299. {
  300.     USEPRT("Usage: xroach [options]\n\n");
  301.     USEPRT("Options:\n");
  302.     USEPRT("       -display displayname\n");
  303.     USEPRT("       -rc      roachcolor\n");
  304.     USEPRT("       -roaches numroaches\n");
  305.     USEPRT("       -speed   roachspeed\n");
  306.     USEPRT("       -squish\n");
  307.     USEPRT("       -rgc     roachgutscolor\n");
  308.     
  309.     exit(1);
  310. }
  311.  
  312. void
  313. SigHandler()
  314. {
  315.        
  316.     /*
  317.        If we are blocked, no roaches are visible and we can just bail
  318.        out.  If we are not blocked, then let the main procedure clean
  319.        up the root window.
  320.     */
  321.     if (eventBlock) {
  322.     XCloseDisplay(display);
  323.     exit(0);
  324.     }
  325.     else {
  326.     done = 1;
  327.     }
  328. }
  329.  
  330. /*
  331.    Find the root or virtual root window.
  332. */
  333. Window
  334. FindRootWindow()
  335. {
  336.     Window rootWin;
  337.     Window realRoot;
  338.     Atom swmVroot;
  339.     Window rootReturn, parentReturn, *children;
  340.     unsigned int numChildren;
  341.     int cx;
  342.     Atom actualType;
  343.     Atom actualFormat;
  344.     unsigned long nItems;
  345.     unsigned long bytesAfter;
  346.     Window *newRoot;
  347.     
  348.     /*
  349.        Get real root window.
  350.     */
  351.     realRoot = rootWin = RootWindow(display, screen);
  352.     
  353.     /*
  354.        Get atom for virtual root property.  If the atom doesn't
  355.        exist, we can assume the corresponding property does not
  356.        exist. 
  357.     */
  358.     swmVroot = XInternAtom(display, "__SWM_VROOT", True);
  359.     
  360.     if (swmVroot == None)
  361.     return rootWin;
  362.     
  363.     /*
  364.        Run children of root, looking for a virtual root.
  365.     */
  366.     XQueryTree(display, rootWin, &rootReturn, &parentReturn, 
  367.             &children, &numChildren);
  368.     for (cx=0; cx<numChildren; cx++) {
  369.     newRoot = NULL;
  370.     nItems = 0;
  371.     if (XGetWindowProperty(display, children[cx], swmVroot, 0L, 1L, False,
  372.         XA_WINDOW, &actualType, &actualFormat, &nItems,
  373.         &bytesAfter, &newRoot) == Success && actualFormat != None) {
  374.         if (nItems >= 1) {
  375.             rootWin = *newRoot;
  376.         }
  377.         if (newRoot) {
  378.             XFree(newRoot);
  379.         }
  380.     }
  381.     if (rootWin != realRoot) break;
  382.     }
  383.     XFree(children);
  384.     
  385.     return rootWin;
  386. }
  387.  
  388. /*
  389.    Generate random integer between 0 and maxVal-1.
  390. */
  391. int
  392. RandInt(maxVal)
  393. int maxVal;
  394. {
  395.     return rand() % maxVal;
  396. }
  397.  
  398. /*
  399.    Check for roach completely in specified rectangle.
  400. */
  401. int
  402. RoachInRect(roach, rx, ry, x, y, width, height)
  403. Roach *roach;
  404. int rx;
  405. int ry;
  406. int x;
  407. int y;
  408. unsigned int width;
  409. unsigned int height;
  410. {
  411.     if (rx < x) return 0;
  412.     if ((rx + roach->rp->width) > (x + width)) return 0;
  413.     if (ry < y) return 0;
  414.     if ((ry + roach->rp->height) > (y + height)) return 0;
  415.     
  416.     return 1;
  417. }
  418.  
  419. /*
  420.    Check for roach overlapping specified rectangle.
  421. */
  422. int
  423. RoachOverRect(roach, rx, ry, x, y, width, height)
  424. Roach *roach;
  425. int rx;
  426. int ry;
  427. int x;
  428. int y;
  429. unsigned int width;
  430. unsigned int height;
  431. {
  432.     if (rx >= (x + width)) return 0;
  433.     if ((rx + roach->rp->width) <= x) return 0;
  434.     if (ry >= (y + height)) return 0;
  435.     if ((ry + roach->rp->height) <= y) return 0;
  436.     
  437.     return 1;
  438. }
  439.  
  440. /*
  441.    Give birth to a roach.
  442. */
  443. void
  444. AddRoach()
  445. {
  446.     Roach *r;
  447.     
  448.     if (curRoaches < maxRoaches) {
  449.     r = &roaches[curRoaches++];
  450.     r->index = RandInt(ROACH_HEADINGS);
  451.     r->rp = &roachPix[r->index];
  452.     r->x = RandInt(display_width - r->rp->width);
  453.     r->y = RandInt(display_height - r->rp->height);
  454.     r->intX = -1;
  455.     r->intY = -1;
  456.     r->hidden = 0;
  457.     r->steps = RandInt(200);
  458.     r->turnLeft = RandInt(100) >= 50;
  459.     }
  460. }
  461.  
  462. /*
  463.    Turn a roach.
  464. */
  465. void
  466. TurnRoach(roach)
  467. Roach *roach;
  468. {
  469.     if (roach->index != (roach->rp - roachPix)) return;
  470.  
  471.     if (roach->turnLeft) {
  472.     roach->index += (RandInt(30) / 10) + 1;
  473.     if (roach->index >= ROACH_HEADINGS)
  474.         roach->index -= ROACH_HEADINGS;
  475.     }
  476.     else {
  477.     roach->index -= (RandInt(30) / 10) + 1;
  478.     if (roach->index < 0)
  479.         roach->index += ROACH_HEADINGS;
  480.     }
  481. }
  482.  
  483. /*
  484.    Move a roach.
  485. */
  486. void
  487. MoveRoach(rx)
  488. int rx;
  489. {
  490.     Roach *roach;
  491.     Roach *r2;
  492.     float newX;
  493.     float newY;
  494.     int ii;
  495.     
  496.     roach = &roaches[rx];
  497.     newX = roach->x + (roachSpeed * roach->rp->cosine);
  498.     newY = roach->y - (roachSpeed * roach->rp->sine);
  499.     
  500.     if (RoachInRect(roach, (int)newX, (int)newY, 
  501.                 0, 0, display_width, display_height)) {
  502.     
  503.     roach->x = newX;
  504.     roach->y = newY;
  505.  
  506.     if (roach->steps-- <= 0) {
  507.         TurnRoach(roach);
  508.         roach->steps = RandInt(200);
  509.     }
  510.  
  511.     for (ii=rx+1; ii<curRoaches; ii++) {
  512.         r2 = &roaches[ii];
  513.         if (RoachOverRect(roach, (int)newX, (int)newY,
  514.         r2->intX, r2->intY, r2->rp->width, r2->rp->height)) {
  515.     
  516.         TurnRoach(roach);
  517.         }
  518.     }
  519.     }
  520.     else {
  521.     TurnRoach(roach);
  522.     }
  523. }
  524.     
  525. /*
  526.    Draw all roaches.
  527. */
  528. void
  529. DrawRoaches()
  530. {
  531.     Roach *roach;
  532.     int rx;
  533.     
  534.     for (rx=0; rx<curRoaches; rx++) {
  535.     roach = &roaches[rx];
  536.     
  537.     if (roach->intX >= 0 && roach->rp != NULL) {
  538.         XClearArea(display, rootWin, roach->intX, roach->intY,
  539.         roach->rp->width, roach->rp->height, False);
  540.     }
  541.     }
  542.     
  543.     for (rx=0; rx<curRoaches; rx++) {
  544.     roach = &roaches[rx];
  545.     
  546.     if (!roach->hidden) {
  547.         roach->intX = roach->x;
  548.         roach->intY = roach->y;
  549.         roach->rp = &roachPix[roach->index];
  550.     
  551.         XSetStipple(display, gc, roach->rp->pixmap);
  552.         XSetTSOrigin(display, gc, roach->intX, roach->intY);
  553.         XFillRectangle(display, rootWin, gc,
  554.         roach->intX, roach->intY, roach->rp->width, roach->rp->height);
  555.     }
  556.     else {
  557.         roach->intX = -1;
  558.     }
  559.     }
  560. }
  561.  
  562. /*
  563.    Cover root window to erase roaches.
  564. */
  565. void
  566. CoverRoot()
  567. {
  568.     XSetWindowAttributes xswa;
  569.     long wamask;
  570.     Window roachWin;
  571.     
  572.     xswa.background_pixmap = ParentRelative;
  573.     xswa.override_redirect = True;
  574.     wamask = CWBackPixmap | CWOverrideRedirect;
  575.     roachWin = XCreateWindow(display, rootWin, 0, 0,
  576.             display_width, display_height, 0, CopyFromParent,
  577.             InputOutput, CopyFromParent, wamask, &xswa);
  578.     XLowerWindow(display, roachWin);
  579.     XMapWindow(display, roachWin);
  580.     XFlush(display);
  581. }    
  582.  
  583. #if !GRAB_SERVER
  584.  
  585. int
  586. RoachErrors(dpy, err)
  587. Display *dpy;
  588. XErrorEvent *err;
  589. {
  590.     errorVal = err->error_code;
  591.     
  592.     return 0;
  593. }
  594.  
  595. #endif /* GRAB_SERVER */
  596.  
  597. /*
  598.    Calculate Visible region of root window.
  599. */
  600. int
  601. CalcRootVisible()
  602. {
  603.     Region covered;
  604.     Region visible;
  605.     Window *children;
  606.     int nChildren;
  607.     Window dummy;
  608.     XWindowAttributes wa;
  609.     int wx;
  610.     XRectangle rect;
  611.     int winX, winY;
  612.     unsigned int winHeight, winWidth;
  613.     unsigned int borderWidth;
  614.     unsigned int depth;
  615.     
  616.     /*
  617.        If we don't grab the server, the XGetWindowAttribute or XGetGeometry
  618.        calls can abort us.  On the other hand, the server grabs can make for
  619.        some annoying delays.
  620.     */
  621. #if GRAB_SERVER
  622.     XGrabServer(display);
  623. #else
  624.     XSetErrorHandler(RoachErrors);
  625. #endif
  626.  
  627.     /*
  628.        Get children of root.
  629.     */
  630.     XQueryTree(display, rootWin, &dummy, &dummy, &children, &nChildren);
  631.     
  632.     /*
  633.        For each mapped child, add the window rectangle to the covered
  634.        region.
  635.     */
  636.     covered = XCreateRegion();
  637.     for (wx=0; wx<nChildren; wx++) {
  638.     if (XEventsQueued(display, QueuedAlready)) {
  639.         XDestroyRegion(covered);
  640.         return 1;
  641.     }
  642.     errorVal = 0;
  643.     XGetWindowAttributes(display, children[wx], &wa);
  644.     if (errorVal) continue;
  645.     if (wa.class == InputOutput && wa.map_state == IsViewable) {
  646.         XGetGeometry(display, children[wx], &dummy, &winX, &winY,
  647.         &winWidth, &winHeight, &borderWidth, &depth);
  648.         if (errorVal) continue;
  649.         rect.x = winX;
  650.         rect.y = winY;
  651.         rect.width = winWidth + (borderWidth * 2);
  652.         rect.height = winHeight + (borderWidth * 2);
  653.         XUnionRectWithRegion(&rect, covered, covered);
  654.     }
  655.     }
  656.     XFree(children);
  657.  
  658. #if GRAB_SERVER
  659.     XUngrabServer(display);
  660. #else
  661.     XSetErrorHandler((ErrorHandler *)NULL);
  662. #endif
  663.     
  664.     /*
  665.        Subtract the covered region from the root window region.
  666.     */
  667.     visible = XCreateRegion();
  668.     rect.x = 0;
  669.     rect.y = 0;
  670.     rect.width = display_width;
  671.     rect.height = display_height;
  672.     XUnionRectWithRegion(&rect, visible, visible);
  673.     XSubtractRegion(visible, covered, visible);
  674.     XDestroyRegion(covered);
  675.     
  676.     /*
  677.        Save visible region globally.
  678.     */
  679.     if (rootVisible)
  680.     XDestroyRegion(rootVisible);
  681.     rootVisible = visible;
  682.     
  683.     
  684.     /*
  685.        Mark all roaches visible.
  686.     */
  687.     for (wx=0; wx<curRoaches; wx++) 
  688.     roaches[wx].hidden = 0;
  689.  
  690.     return 0;
  691. }
  692.  
  693. /*
  694.    Mark hidden roaches.
  695. */
  696. int
  697. MarkHiddenRoaches()
  698. {
  699.     int rx;
  700.     Roach *r;
  701.     int nVisible;
  702.     
  703.     nVisible = 0;
  704.     for (rx=0; rx<curRoaches; rx++) {
  705.     r = &roaches[rx];
  706.     
  707.     if (!r->hidden) {
  708.         if (r->intX > 0 && XRectInRegion(rootVisible, r->intX, r->intY,
  709.                 r->rp->width, r->rp->height) == RectangleOut) {
  710.         r->hidden = 1;
  711.         }
  712.         else {
  713.         nVisible++;
  714.         }
  715.     }
  716.     }
  717.     
  718.     return nVisible;
  719. }
  720.  
  721. /*
  722.    Allocate a color by name.
  723. */
  724. Pixel
  725. AllocNamedColor(colorName, dfltPix)
  726. char *colorName;
  727. Pixel dfltPix;
  728. {
  729.     Pixel pix;
  730.     XColor scrncolor;
  731.     XColor exactcolor;
  732.  
  733.     if (XAllocNamedColor(display, DefaultColormap(display, screen),
  734.         colorName, &scrncolor, &exactcolor)) {
  735.         pix = scrncolor.pixel;
  736.     }
  737.     else {
  738.         pix = dfltPix;
  739.     }
  740.  
  741.     return pix;
  742. }
  743.  
  744. /*
  745.  *    squishCheck - Check to see if we have to squish any roaches.
  746.  */
  747. checkSquish(buttonEvent)
  748. XButtonEvent *buttonEvent;
  749. {
  750.     int x, y;
  751.     int i;
  752.     int rx;
  753.     Roach *r;
  754. /* */
  755.     x = buttonEvent->x;
  756.     y = buttonEvent->y;
  757.  
  758.     for (rx=0; rx<curRoaches; rx++) {
  759.     r = &roaches[rx];
  760.     if (r->rp == NULL) continue;
  761.  
  762.     if (x > r->intX &&
  763.         x < (r->intX + r->rp->width) &&
  764.         y > r->intY &&
  765.         y < (r->intY + r->rp->height)) {
  766.         XSetStipple(display, gutsGC, squishMap);
  767.         XSetTSOrigin(display, gutsGC, r->intX, r->intY);
  768.         XFillRectangle(display, rootWin, gutsGC,
  769.         r->intX, r->intY, squish_width, squish_height);
  770.  
  771.         /*
  772.          * Delete the roach
  773.          */
  774.         for (i = rx; i < curRoaches - 1; i++)
  775.             roaches[i] = roaches[i + 1];
  776.     
  777.         curRoaches--;
  778.         rx--;
  779.     }
  780.     }
  781.  
  782.     return;
  783. }
  784.